package org.zjt.proxy.jdk;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author juntao.zhang
 * @version V1.0
 * @Description: TODO
 * @Package org.zjt.proxy.jdk
 * @date 2018/7/3 20:12
 *
 *       1、Proxy 生成Proxy 并实现 接口的包装类。
 *       2、Proxy 实例化，将invokeHandler 作为属性传入。
 *       3、执行Proxy方法时候，利用反射执行invokeHandler中的方法。
 *       4、invokeHandler中通过反射调用被包装bean中的方法。
 */
@Slf4j
public class ProxyClassGenerator {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        MyProxyClassFactory myProxyClassFactory = new MyProxyClassFactory(contextClassLoader);
        Class<?> aClass = myProxyClassFactory.apply(contextClassLoader, new Class[]{ISubject.class});
        log.info(String.valueOf(aClass));

        Constructor<?> constructor = aClass.getConstructor(new Class[]{InvocationHandler.class});
        ISubject iSubject = (ISubject) constructor.newInstance(new MyInvocationHandler());

        log.info(iSubject.toString());
    }



    @Slf4j
    public static class MyInvocationHandler implements InvocationHandler{

        private Subject subject = new Subject();

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            log.info("----执行目标bean中的方法--proxy:{}\tproxy class :{}",proxy,proxy.getClass());

            return method.invoke(subject,args);
        }
    }
}
